package com.chianghao.rock.system.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.constraints.NotBlank;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.chianghao.core.web.R;
import com.chianghao.core.web.ValidatedGroup;
import com.chianghao.rock.Constant;
import com.chianghao.rock.admin.system.route.dto.ApiDto;
import com.chianghao.rock.admin.system.route.dto.ButtonDto;
import com.chianghao.rock.admin.system.route.dto.RouteDto;
import com.chianghao.rock.admin.system.route.dto.RouteModifyDto;
import com.chianghao.rock.admin.system.route.vo.ApiVo;
import com.chianghao.rock.admin.system.route.vo.ButtonVo;
import com.chianghao.rock.admin.system.route.vo.RouteTreeVo;
import com.chianghao.rock.admin.system.route.vo.RouteVo;
import com.chianghao.rock.common.SequenceService;
import com.chianghao.rock.system.entity.Route;
import com.chianghao.rock.system.service.route.RouteService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;


@RestController
@RequestMapping("system/route")
@Api(value="路由",tags={"路由"})
public class RouteController {

    @Autowired
    RouteService routeService;

    @Autowired
    SequenceService sequenceService;
    
	@PostMapping("add")
	@ApiOperation(value="添加路由")
	public R<Boolean> add(@Validated({ValidatedGroup.Add.class}) RouteDto dto) {
		Route route = toEntity(dto);
		Long id  = sequenceService.getNextId();
		route.setId(id);
		route.setType(0);
		if(dto.getParentId()==null) {
			route.setParentId(Constant.rootId);
		}
		routeService.doCreate(route);
		return R.getSuccess(true);
	}

	@PostMapping("add-button")
	@ApiOperation(value="添加按钮")
    public R<Boolean> addButton(ButtonDto dto){
		Route route = buttonDtoToEntity(dto);
		Long id  = sequenceService.getNextId();
		route.setId(id);
		route.setType(1);
		routeService.doCreateButtonOrApi(route);
    	return R.getSuccess(true);
    }
    
    @PostMapping("add-api")
    @ApiOperation(value="添加API")
    public R<Boolean> addApi(ApiDto dto){
    	Route route = apiToEntity(dto);
		Long id  = sequenceService.getNextId();
		route.setId(id);
		route.setType(2);
		routeService.doCreateButtonOrApi(route);
    	return R.getSuccess(true);
    }
	
    @PostMapping("modify")
    @ApiOperation(value="修改路由")
    public R<Boolean> modify(@Validated({ValidatedGroup.Modify.class}) RouteModifyDto dto) {
    	Route route = toEntity(dto);
		routeService.modify(route);
    	return R.getSuccess(true);
	}

    
    @PostMapping("modify-button")
    @ApiOperation(value="修改按钮")
    public R<Boolean> modify(@Validated({ValidatedGroup.Modify.class}) ButtonDto dto) {
    	Route route = buttonDtoToEntity(dto);
		routeService.modiyButtonOrApi(route);
    	return R.getSuccess(true);
	}
    
    @PostMapping("modify-api")
    @ApiOperation(value="修改API")
    public R<Boolean> modify(@Validated({ValidatedGroup.Modify.class}) ApiDto dto) {
    	Route route = apiToEntity(dto);
		routeService.modiyButtonOrApi(route);
    	return R.getSuccess(true);
	}
    
    @DeleteMapping("delete")
    @ApiOperation(value="删除")
    @ApiImplicitParam(name = "id", value = "主键", paramType = "query", required = true, dataType = "String")
    public R<Boolean> delete(@NotBlank(message="error:id,not.null") Long id) {
    	routeService.delete(id);
    	return R.getSuccess(true);
    }

    @GetMapping("detail")
    @ApiOperation(value="明细")
    @ApiImplicitParam(name = "id", value = "主键", paramType = "query", required = true, dataType = "String")
    public R<RouteVo> detail(@NotBlank(message="error:id,not.null") Long id) {
    	Route  bean = routeService.queryOneById(id);
    	return R.getSuccess(toVo(bean));
    }

    @GetMapping("tree")
    @ApiOperation(value="查新树")
    public R<List<RouteTreeVo>> queryTree() {
    	List<Route> list = routeService.queryAllRoute();
    	return R.getSuccess(toRouteTreeListVo(list,Constant.rootId));
    }
    
    @GetMapping("api-list")
    @ApiOperation(value="api结合")
    @ApiImplicitParam(name = "parentId", value = "父主键", paramType = "query", required = true, dataType = "String")
    public R<List<ApiVo>> queryApi(@NotBlank(message="error:parent.id,not.null") Long parentId) {
    	List<Route> list  = this.routeService.queryChildrenEqualType(parentId,2);
    	return R.getSuccess(toApiListVo(list));
    }
    
    @GetMapping("button-list")
    @ApiOperation(value="按钮结合")
    @ApiImplicitParam(name = "parentId", value = "父主键", paramType = "query", required = true, dataType = "String")
    public R<List<ButtonVo>> queryButton(@NotBlank(message="error:parent.id,not.null") Long parentId) {
    	List<Route> list  = this.routeService.queryChildrenEqualType(parentId,1);
    	return R.getSuccess(toButtonListVo(list));
    }
    
    
    private List<RouteTreeVo> toRouteTreeListVo(List<Route> routes,Long parentId){
    	List<RouteTreeVo> list = new ArrayList<RouteTreeVo>();
    	for(Route r:routes) {
    		if(r.getParentId().longValue()==parentId.longValue()) {
    			RouteTreeVo item  = toRouteTree(r);
    			List<RouteTreeVo> childList  = toRouteTreeListVo(routes,r.getId());
    			if(childList!=null&&!childList.isEmpty()) {
    				item.setChildren(childList);
    			}
    			list.add(item);
    		}
    	}
    	Collections.sort(list, new Comparator<RouteTreeVo>() {
			@Override
			public int compare(RouteTreeVo o1, RouteTreeVo o2) {
				return o1.getSort()-o2.getSort();
			}
		});
    	return list;
    }
    
    
    //// entity ---> vo
    private List<ButtonVo> toButtonListVo(List<Route> list){
    	List<ButtonVo> array = list.stream().map(item->toButtonVo(item)).collect(Collectors.toList());
    	return array;
    }
    
    private List<ApiVo> toApiListVo(List<Route> list){
    	List<ApiVo> array = list.stream().map(item->toApiVo(item)).collect(Collectors.toList());
    	return array;
    }
    
    private RouteVo toVo(Route bean) {
    	RouteVo vo = new RouteVo();
    	BeanUtils.copyProperties(bean, vo);
    	return vo;
    }
    
    private RouteTreeVo toRouteTree(Route bean) {
    	RouteTreeVo vo = new RouteTreeVo();
    	BeanUtils.copyProperties(bean, vo);
    	return vo;
    }
    
    private ButtonVo toButtonVo(Route bean) {
    	ButtonVo vo = new ButtonVo();
    	BeanUtils.copyProperties(bean, vo);
    	return vo;
    }
    
    private ApiVo toApiVo(Route bean) {
    	ApiVo vo = new ApiVo();
    	BeanUtils.copyProperties(bean, vo);
    	return vo;
    }
    
    
    ////////  dto  --->entity
    private Route buttonDtoToEntity(ButtonDto dto) {
    	Route bean = new Route();
    	BeanUtils.copyProperties(dto, bean);
    	return bean;
    }
    
    private Route apiToEntity(ApiDto dto) {
    	Route bean = new Route();
    	BeanUtils.copyProperties(dto, bean);
    	return bean;
    }
    
    private Route toEntity(RouteDto dto) {
    	Route bean = new Route();
    	BeanUtils.copyProperties(dto, bean);
    	return bean;
    }
    
    private Route toEntity(RouteModifyDto dto) {
    	Route bean = new Route();
    	BeanUtils.copyProperties(dto, bean);
    	return bean;
    }

}